import 'package:flutter/material.dart';

class NotificationPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    String _msg = "";
    return Scaffold(
      appBar: AppBar(
        title: Text("Notification"),
      ),
      body: Flex(
        direction: Axis.vertical,
        children: <Widget>[
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.blue[50],
              child: NotificationListener(
                /// 它的返回值类型为布尔值，当返回值为true时，阻止冒泡，其父级Widget将再也收不到该通知；
                /// 当返回值为false 时继续向上冒泡通知。
                onNotification: (notification) {
                  switch (notification.runtimeType) {
                    case ScrollStartNotification: print("开始滚动"); break;
                    case ScrollUpdateNotification: print("正在滚动"); break;
                    case ScrollEndNotification: print("停止滚动"); break;
                    case OverscrollNotification: print("滚动到边界"); break;
                  }
                },
                child: ListView.builder(
                  itemCount: 100,
                  itemBuilder: (context, index) => ListTile(title: Text("$index")),
                ),
              ),
            )
          ),
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.red[50],
              /// NotificationListener 可以指定一个模板参数，该模板参数类型必须是继承自Notification；
              /// 当显式指定模板参数时，NotificationListener 便只会接收该参数类型的通知。
              child: NotificationListener<ScrollEndNotification>(
                onNotification: (notification) {
                  print("scroll end : $notification");
                },
                child: ListView.builder(
                  itemCount: 100,
                  itemBuilder: (context, index) => ListTile(title: Text("$index")),
                ),
              ),
            )
          ),
          Expanded(
            flex: 1,
            child: Container(
              color: Colors.green[50],
              child: StatefulBuilder(builder: (context, _setState) {
                return NotificationListener<_MyNotification>(
                  onNotification: (notification) {
                    _setState(() {
                      _msg += notification.msg + " ";
                    });
                    return true;
                  },
                  child: Center(
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                        ///
                        /// 注释的部分是不能正常工作的，因为这个context是根Context，
                        /// 而NotificationListener是监听的子树，所以我们通过Builder
                        /// 来构建RaisedButton，来获得按钮位置的context。
                        /// 
                        // RaisedButton(
                        //   onPressed: () => _MyNotification("Hi").dispatch(context),
                        //   child: Text("Send Notification"),
                        // ),
                        //
                        Builder(
                          builder: (context) {
                            return RaisedButton(
                              /// Notification有一个dispatch(context)方法，它是用于分发通知的，
                              /// 我们说过context实际上就是操作Element的一个接口，它与Element树上
                              /// 的节点是对应的，通知会从context对应的Element节点向上冒泡。
                              onPressed: () => _MyNotification("Hi").dispatch(context),
                              child: Text("Send Notification"),
                            );
                          },
                        ),
                        Text(_msg)
                      ],
                    ),
                  ),
                );
              })
            )
          ),

          Expanded(
            flex: 1,
            child: Container(
              color: Colors.cyan[50],
              child: StatefulBuilder(builder: (context, _setState) {
                return NotificationListener<_MyNotification>(
                  onNotification: (notification) {
                    _setState(() => _msg += notification.msg + " ");
                    return false;
                  },
                  child: NotificationListener<_MyNotification>(
                    onNotification: (notification) {
                      _setState(() => _msg += notification.msg + " ");
                      // 如果改为false，那么每次点击会有两个hi
                      // 返回true则会阻止通知冒泡
                      return true;
                    },
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                        Builder(
                          builder: (context) => RaisedButton(
                            onPressed: () => _MyNotification("Hi").dispatch(context),
                            child: Text("Send Notification"),
                          ),
                        ),
                        Text(_msg)
                      ],
                    ),
                  ),
                );
              }),
            ),
          )
        ],
      ),
    );
  }
}

class _MyNotification extends Notification {
  _MyNotification(this.msg);
  final String msg;
}